/*
 * FileAsMsg plug-in for Miranda IM and QIP Infium.
 * Sending/receiving files via instant messaging without protocol support.
 * Homepage: http://code.google.com/p/fileasmsg/
 *
 * Copyright (c) 2008, Radist <radist.nt@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Name(s) of contributor(s) may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Radist ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Radist BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __FILEASMESSAGE_THREADS__H__R___
#define __FILEASMESSAGE_THREADS__H__R___

#include <Windows.h>
#include <map>

#define _REQUIRE_EVENT
#define _REQUIRE_CS
#define _REQUIRE_TIMER

#ifdef _REQUIRE_EVENT

class WaitableObject
{
protected:
	HANDLE obj;
	WaitableObject(){}
	~WaitableObject()
	{
		CloseHandle(obj);
	}
public:
	DWORD WaitFor(DWORD timeout, bool handle_messages = false);
	HANDLE handle(void)
	{
		return obj;
	}
};

class Event
	:public WaitableObject
{
public:
	Event(bool ManualReset = false, bool InitialState = false)
	{
		obj = CreateEventW(NULL, ManualReset, InitialState, NULL);
	}
	void Set(void)
	{
		SetEvent(obj);
	}
	void Reset(void)
	{
		ResetEvent(obj);
	}
};

#ifdef _REQUIRE_TIMER

class WaitableTimer
	:public WaitableObject
{
public:
	WaitableTimer(bool ManualReset = false)
	{
		obj = CreateWaitableTimerW(NULL, ManualReset, NULL);
	}
	void Set(DWORD WaitPeriod)
	{
		LARGE_INTEGER period;
		period.QuadPart = (long long)(-10000) * WaitPeriod;
		SetWaitableTimer(obj, &period, 0, NULL, NULL, false);
	}
	void Cancel(void)
	{
		CancelWaitableTimer(obj);
	}
};

#endif//_REQUIRE_TIMER
#endif//_REQUIRE_EVENT

#if defined(_REQUIRE_TIMER) && !defined(_REQUIRE_CS)
#define _REQUIRE_CS
#endif

#ifdef _REQUIRE_CS
class CriticalSection
{
	CRITICAL_SECTION cs;
	void Enter(void)
	{
		EnterCriticalSection(&cs);
	}
	void Leave(void)
	{
		LeaveCriticalSection(&cs);
	}
	friend class Locker;
public:
	CriticalSection()
	{
		InitializeCriticalSectionAndSpinCount(&cs, 10);
	}
	~CriticalSection()
	{
		DeleteCriticalSection(&cs);
	}
};

class Locker
{
	CriticalSection &cs;
	Locker(): cs(*(CriticalSection*)NULL) {}
public:
	Locker(CriticalSection&_cs): cs(_cs)
	{
		cs.Enter();
	}
	~Locker()
	{
		cs.Leave();
	}
};
#endif//_REQUIRE_CS

#ifdef _REQUIRE_TIMER
class Timer
{
	UINT hTimer;
	DWORD interval;
	bool active;
	bool single;
	static CriticalSection cs;
	static std::map<UINT,Timer*> timers;
	static void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);
protected:
	virtual void Tick(void)=0;
public:
	Timer(DWORD _interval, bool _single = false, bool _start = false);
	~Timer();
	void SetInterval(DWORD _interval);
	void Start();
	void Stop();
};
#endif//_REQUIRE_TIMER


#endif//__FILEASMESSAGE_THREADS__H__R___
